{# Form macros. Native inputs with ``name`` attributes, so every form posts or re-queries through htmx without client-side state. {% from "components/macros/form.html" import field, text_input, select, date_input, primary_button %} #} {% from "components/macros/icons.html" import icon %} {# One button height: a primary button (Save) stands as tall as an action (Read pages). Only a form's full-width submit (sign in) is larger. #} {%- set _button_size = "px-2.5 py-1 text-xs" -%} {%- set _primary_button_classes -%} text-aegis-text border border-aegis-teal bg-aegis-teal/10 rounded hover:bg-aegis-teal/20 transition-colors disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center justify-center gap-2 {%- endset -%} {# Inline primary button (no loading spinner). Defaults to ``type="button"`` so it doesn't accidentally submit a form it's nested inside — pass ``type="submit"`` explicitly when you want submit semantics. ``attrs`` lets the caller pass other attributes (Alpine ``@click``, ``:disabled``, ``aria-*``), never a ``type=`` (refused). #} {% macro primary_button(label, type="button", attrs="") %} {% endmacro %} {# Primary submit button with an inline loading spinner. Parent scope must expose ``loading`` (bool) — typically flipped by ``@submit="loading = true"`` on the form. The button disables itself while loading so a double-click can't double-submit. #} {% macro submit_button(idle_label, loading_label) %} {% endmacro %} {# Shared input styling; every control below uses it so the bar reads as one. #} {%- set _control_classes -%} bg-aegis-bg border border-aegis-border rounded px-2.5 py-1.5 text-sm text-aegis-text placeholder:text-aegis-muted/50 focus:border-aegis-teal focus:outline-none transition-colors [&:user-invalid]:border-error {%- endset -%} {# A native select. ``options`` are objects or dicts with ``id`` and ``name``, or, ``grouped``, ``{"label", "options"}`` groups of them (an optgroup each); ``blank`` is the "no filter" label (``None`` for no blank choice), chosen while nothing is; ``selected`` the current id. ``label`` wraps it inline for a filter bar; ``block`` lays it out full-width inside a ``field()``; ``attrs`` rides on the select. #} {% macro select(name, options, selected=None, blank="All", label=None, block=False, grouped=False, attrs="") %} {% if label %}{% endif %} {% endmacro %} {% macro date_input(name, value=None, label=None, block=False) %} {% if label %}{% endif %} {% endmacro %} {# Every file picker: the native input hidden behind a button-styled label, so it looks like every other button. Picking submits its form (an upload button); with ``submit=False`` it keeps what was picked (a second pick adds to the first, where ``multiple``), says how many and how big, and lists each, removable (the ``filePicker`` component in app.js), for a form with its own submit. #} {% macro file_button(id, label, accept=None, name="file", submit=True, required=True, multiple=False) %} {%- set button = "inline-flex items-center cursor-pointer " ~ _button_size ~ " leading-normal rounded border border-aegis-teal text-aegis-text hover:bg-aegis-teal/10 transition-colors" -%} {%- set input -%}{%- endset -%} {%- set picker -%}{{ input }}{%- endset -%} {% if submit %} {{ picker }} {% else %}
{{ error }}
{% endif %} {% if hint %}{{ hint }}
{% endif %}